Skip to content

feat: dashboard polish — skeletons, error boundaries, responsive cards#72

Open
GalDayan wants to merge 1 commit intomainfrom
dashboard-polish
Open

feat: dashboard polish — skeletons, error boundaries, responsive cards#72
GalDayan wants to merge 1 commit intomainfrom
dashboard-polish

Conversation

@GalDayan
Copy link
Copy Markdown
Contributor

Changes

Loading Skeletons

  • New Skeleton base component + dashboard-skeletons.tsx with tab-specific skeletons
  • Initial load shows skeleton layout (nav bar + stats cards + agent list) instead of a centered spinner
  • Preserves page structure during load — no layout shift

Error Boundaries

  • New ErrorBoundary component with friendly error UI and retry button
  • Each tab (Agents, Sessions, Analytics, Projects) wrapped independently
  • One tab crashing won't take down the whole dashboard

Responsive Agent Cards

  • Cards stack vertically on mobile, horizontal on sm:+
  • Removed hardcoded min-w-[80px] / min-w-[200px] — uses min-w-0 + truncate instead
  • Stats grid: grid-cols-2 on mobile, flex row on desktop
  • Pause/Resume button full-width on mobile, auto-width on desktop

Technical

  • 5 files changed, 265 additions, 50 deletions
  • Zero TypeScript errors
  • No new dependencies

…ive agent cards

- Add Skeleton, ErrorBoundary, and dashboard skeleton components
- Replace full-page spinner with skeleton layout (nav + stats + agents)
- Wrap each tab in ErrorBoundary for graceful per-tab error recovery
- Fix agent cards: responsive stacking on mobile, truncate overflow
- Remove hardcoded min-w values, use grid-cols-2 on small screens
- Zero TS errors
Copilot AI review requested due to automatic review settings March 25, 2026 01:29
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Polishes the dashboard UX by replacing the initial spinner with layout-preserving skeletons, introducing per-tab error boundaries to isolate failures, and improving agent card responsiveness for mobile layouts.

Changes:

  • Add a shared Skeleton component and tab-oriented dashboard skeleton layouts.
  • Add a reusable ErrorBoundary and wrap each dashboard tab independently.
  • Refactor agent list cards to stack on mobile and truncate text instead of using hard min-widths.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
frontend/src/components/ui/skeleton.tsx Adds a base skeleton UI primitive.
frontend/src/components/ui/error-boundary.tsx Adds a client-side error boundary with retry UI.
frontend/src/components/ui/dashboard-skeletons.tsx Adds skeleton layouts for dashboard sections/tabs.
frontend/src/app/dashboard/page.tsx Uses skeletons during load and wraps tab content in error boundaries.
frontend/src/app/dashboard/components/AgentsTab.tsx Updates agent cards to be responsive (mobile stacking, truncation, button sizing).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

</nav>
<div className="max-w-7xl mx-auto px-6 py-6 space-y-6">
<StatsOverviewSkeleton />
<AgentsTabSkeleton />
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When loading is true, the page always renders AgentsTabSkeleton() regardless of the active tab (e.g. ?tab=sessions / ?tab=analytics). This causes a mismatched skeleton for deep links. Render the skeleton corresponding to the current tab (and consider adding a projects skeleton or a generic one).

Suggested change
<AgentsTabSkeleton />
{tab === "sessions"
? <SessionsTabSkeleton />
: tab === "analytics"
? <AnalyticsTabSkeleton />
: <AgentsTabSkeleton />}

Copilot uses AI. Check for mistakes.
<div className="text-xs text-muted-foreground mb-4 max-w-md mx-auto break-words">
{this.state.error?.message || "An unexpected error occurred"}
</div>
<button
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The retry control is a plain <button> without an explicit type. If this boundary is ever rendered inside a <form>, the default type="submit" can cause unintended form submissions. Set type="button" on this button.

Suggested change
<button
<button
type="button"

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +3
import { cn } from "@/lib/utils"

function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skeleton uses React.ComponentProps but the file doesn’t import React (or ComponentProps) anywhere. With the repo’s TS config this will fail to typecheck (Cannot find namespace 'React'). Import * as React or switch to import type { ComponentProps } from "react" and use ComponentProps<"div">.

Suggested change
import { cn } from "@/lib/utils"
function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
import type { ComponentProps } from "react"
import { cn } from "@/lib/utils"
function Skeleton({ className, ...props }: ComponentProps<"div">) {

Copilot uses AI. Check for mistakes.
import { getAgents, getAlerts, getAlertDetails, getCosts, pauseAgent, resumeAgent, acknowledgeAlert, acknowledgeAllAlerts, getSessions, getProjects, getProfiles, getVersion, getAnalytics, getSpend, setCostLimits, isUsingMockData } from "@/lib/api";
import { ClaWatchLogo, ClaWatchIcon } from "@/components/clawatch-logo";
import { ErrorBoundary } from "@/components/ui/error-boundary";
import { StatsOverviewSkeleton, AgentsTabSkeleton, SessionsTabSkeleton, AnalyticsTabSkeleton } from "@/components/ui/dashboard-skeletons";
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused imports: SessionsTabSkeleton and AnalyticsTabSkeleton are imported here but never referenced in this file. This will trip Next/ESLint no-unused-vars during CI. Remove them or use them in the loading UI.

Suggested change
import { StatsOverviewSkeleton, AgentsTabSkeleton, SessionsTabSkeleton, AnalyticsTabSkeleton } from "@/components/ui/dashboard-skeletons";
import { StatsOverviewSkeleton, AgentsTabSkeleton } from "@/components/ui/dashboard-skeletons";

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants